package cn.tedu.work;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * 模拟工作模式中的消费者
 */

public class WorkConsumer {
    //先准备一个main方法
    public static void main(String[] args) throws IOException, TimeoutException {
        //创建连接工厂对象 ConnectionFactory
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.8.100");//设置RabbitMQ的IP地址,这里用的是虚拟机里面的rabbitmq
        connectionFactory.setPort(5672);//设置RabbitMQ的端口号,这里5672是默认的端口号，也可以不写
        connectionFactory.setUsername("tom");//设置用户名
        connectionFactory.setPassword("tom");//设置密码
        connectionFactory.setVirtualHost("/");//设置虚拟主机,如果不指定，默认是 “/”

        //1. 创建tcp连接对象connection（通过ConnectionFactory创建）
        Connection connection = connectionFactory.newConnection();

        //2. 创建channel连接对象（通过Connection创建）
        Channel channel = connection.createChannel();

        //3.通过channel创建队列
        /**
         * 第一个参数：队列的名称
         * 第二个参数：队列是否持久化
         * 第三个参数：队列是否独占
         * 第四个参数：队列是否自动删除
         * 第五个参数：其他属性设置
         */
        channel.queueDeclare("work.queue",true,false,false,null);

        //4. 消费数据
        //4.1 编写消息处理的回调函数
        DeliverCallback deliverCallback = new DeliverCallback() {
            @Override
            public void handle(String consumerTag, Delivery message) throws IOException {
                //message里面封装了要处理的消息
                byte[] body = message.getBody();//获取消息
                //转成对应数据类型的数据进行处理
                String msg = new String(body);
                System.out.println(consumerTag+"要处理"+ msg +"消息数据了");
                System.out.println("数据开始处理");
                for (int i=0;i<msg.length();i++){
                    //模拟处理繁忙的场景，每遇到一个“.”,就sleep一秒
                    if (msg.charAt(i) == '.'){
                        try {
                            Thread.sleep(1000);
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }
                System.out.println(consumerTag+"消息处理完毕");
                //主动向服务器端发送消息回执
                long ackTag = message.getEnvelope().getDeliveryTag();
                //第二个参数：是否发送全部消息的回执消息
                channel.basicAck(ackTag,false);
                System.out.println("----------------------------------------");
            }
        };
        //4.2 编写取消接收数据的回调函数
        CancelCallback cancelCallback = new CancelCallback() {
            @Override
            public void handle(String consumerTag) throws IOException {

            }
        };
        /**
         * 第1个参数：队列的名称
         * 第2个参数：autoACK 是否自动确认，如果设置为true，则自动确认，如果设置为false，则需要手动确认
         * 第3个参数：deliverCallback  用于消息处理的回调函数
         * 第4个参数：cancelCallback  取消接收数据的回调函数
         */
        //实现合理分发，只修改第2个参数的值，无法实现手动ack
        channel.basicQos(1);  //设置消费者只能获取一个消息
        channel.basicConsume("work.queue",false,deliverCallback,cancelCallback);

    }
}
